package com.meilai.project.util.ppt;

import com.meilai.project.dto.business.installOrder.WorkOrderReportInfoDTO;
import com.meilai.project.util.OssAliyunUtil;
import com.meilai.project.vo.business.installOrder.WorkOrderReportPhotoReformDateRangeVO;
import com.meilai.project.vo.business.installOrder.WorkOrderReportPhotoReformInnerVO;
import com.meilai.project.vo.business.installOrder.WorkOrderReportPhotoReformVO;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.sl.usermodel.TableCell;
import org.apache.poi.sl.usermodel.TextParagraph;
import org.apache.poi.sl.usermodel.TextShape;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.xslf.usermodel.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author 张驰
 * @date 2021/7/14 16:37
 */
@Component
@Log4j2
public class NewExportPPTUtil {
    @Value("{spring.profiles.active}")
    private String evn;
    @Autowired
    private OssAliyunUtil ossAliyunUtil;
    @Value("#{${oss-use}}")
    private int useOss;

    public String genWorkOrderReport2(WorkOrderReportInfoDTO data, String modelPath, String outFileSpace, String fileName) {
        // 读取ppt模板
        XMLSlideShow ppt = null;
        try {
            FileInputStream is = new FileInputStream(modelPath);
            ppt = new XMLSlideShow(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (ppt == null) return "";

        // 首页
        // 替换文本map
        HashMap<String, String> replaceMap = new HashMap<>();
        replaceMap.put("${companyName}", StringUtils.defaultString(data.getCompany_name(), ""));
        replaceMap.put("${title}", StringUtils.defaultString(data.getTitle(), ""));
        replaceMap.put("${subTitle}", StringUtils.defaultString(data.getSub_title(), ""));
        replaceMap.put("${count}", "点位：" + StringUtils.defaultString(data.getCount() != null ? data.getCount().toString() : "0") + "个");
        replaceMap.put("${customerName}", data.getShow_customer() ? ("客户：" + StringUtils.defaultString(data.getCustomer_name(), "")) : "");
        replaceMap.put("${type}", StringUtils.defaultString(data.getType(), ""));
        List<String> daterangeList = data.getDaterange();
        if (CollectionUtils.isEmpty(daterangeList)) daterangeList = new ArrayList<>();
        if (!data.getShow_daterange()) daterangeList = new ArrayList<>();
        daterangeList.add("制作日期：" + data.getCreate_time());
        String daterangeStr = String.join("\r", daterangeList);
        replaceMap.put("${daterange}", StringUtils.defaultString(daterangeStr, ""));

        int buildingExtraTurns = 0;

        Dimension pptPageSize = ppt.getPageSize();
        log.info("ppt_w:{},ppt_h:{}", pptPageSize.getWidth(), pptPageSize.getHeight());

        ppt.removeSlide(5);
        ppt.removeSlide(4);
        ppt.removeSlide(1);

        List<XSLFSlide> slides = ppt.getSlides();
        for (int i = 0; i < slides.size(); i++) {
            XSLFSlide slide = slides.get(i);
            List<XSLFShape> shapes = slide.getShapes();

            if (i == 0) {
                // 首页替换文本
                for (XSLFShape shape : shapes) {
                    //修改文本数据利用textshape
                    if (shape instanceof TextShape) {
                        List<XSLFTextParagraph> textParagraphs = ((TextShape) shape).getTextParagraphs();
                        if (textParagraphs == null || textParagraphs.size() == 0) {
                            continue;
                        }
                        replaceText(textParagraphs, replaceMap);
                    }
                }
            }

            if (i == 1) {
                // 第二页
                boolean hasNextTablePage = false;
                String[][] remainBs = null;
                int dataLength = 0;
                for (XSLFShape shape : shapes) {
                    if (shape instanceof XSLFTable) {
                        XSLFTable table = (XSLFTable) shape;
                        // 设置标题行
                        setBuildingHeader(table, data.getBuildingTableHeader());

                        /** 设置表格 x ,y ,width,height **/
                        Rectangle2D tableAnchor = table.getAnchor();
                        Rectangle2D toTableAnchor = new Rectangle2D.Double(((pptPageSize.getWidth() - tableAnchor.getWidth()) / 2),
                                tableAnchor.getY(), tableAnchor.getWidth(), tableAnchor.getHeight());
                        table.setAnchor(toTableAnchor);

                        // 插入表格行
                        String[][] originBs = data.getBuildingTableData();
                        if (originBs != null) {
                            int firstLength = Math.min(originBs.length, 10);
                            dataLength = data.getBuildingTableHeader().length;
                            String[][] firstBs = new String[firstLength][dataLength];
                            if (originBs.length <= 10) {
                                firstBs = originBs;
                                remainBs = null;
                            } else {
                                System.arraycopy(originBs, 0, firstBs, 0, 10);
                                hasNextTablePage = true;
                                remainBs = new String[originBs.length - 10][dataLength];
                                System.arraycopy(originBs, 10, remainBs, 0, originBs.length - 10);
                            }
                            addBuildingData(table, firstBs, 1);
                        }
                    }
                }
                if (hasNextTablePage && remainBs != null) {
                    int pageSize = 15;
                    int remainLength = remainBs.length;
                    buildingExtraTurns = remainLength / pageSize;
                    int mod = remainLength % pageSize;
                    if (mod > 0) buildingExtraTurns++;
                    for (int j = 1; j <= buildingExtraTurns; j++) {
                        int max = j * pageSize;
                        if (max > remainLength) max = remainLength;
                        int curLength = max - (j - 1) * pageSize;
                        String[][] curDatas = new String[curLength][dataLength];
                        System.arraycopy(remainBs, (j - 1) * pageSize, curDatas, 0, curLength);
                        XSLFSlide newSlide = copySlide(ppt, slides.get(2), 2 + j);
                        for (XSLFShape shape : newSlide.getShapes()) {
                            if (shape instanceof XSLFTable) {
                                XSLFTable table = (XSLFTable) shape;
                                // 设置标题行
                                setBuildingHeader(table, data.getBuildingTableHeader());

                                /** 设置表格 x ,y ,width,height **/
                                Rectangle2D tableAnchor = table.getAnchor();
                                Rectangle2D toTableAnchor = new Rectangle2D.Double(((pptPageSize.getWidth() - tableAnchor.getWidth()) / 2),
                                        tableAnchor.getY(), tableAnchor.getWidth(), tableAnchor.getHeight());
                                table.setAnchor(toTableAnchor);

                                // 插入表格行
                                addBuildingData(table, curDatas, 11 + (j - 1) * pageSize);
                            }
                        }
                    }
                }
            }
        }
        ppt.removeSlide(2);
        if (CollectionUtils.isNotEmpty(data.getPhotos())) {
            int NO = 0;
            List<WorkOrderReportPhotoReformInnerVO> photos = new ArrayList<>();
            for (WorkOrderReportPhotoReformVO building : data.getPhotos()) {
                if (building.getDaterangeVOs().size() > 0) {
                    int maxCount = 0;
                    for (WorkOrderReportPhotoReformDateRangeVO dateRangeVO : building.getDaterangeVOs()) {
                        for (WorkOrderReportPhotoReformInnerVO point : dateRangeVO.getPoints()) {
                            WorkOrderReportPhotoReformInnerVO newP = new WorkOrderReportPhotoReformInnerVO();
                            BeanUtils.copyProperties(point, newP);
                            int curIdx = new Integer(newP.getIdx());
                            newP.setIdx(String.valueOf(NO + curIdx));
                            newP.setBuilding_area(building.getBuilding_area());
                            if (curIdx > maxCount) maxCount = curIdx;
                            photos.add(newP);
                        }
                    }
                    NO += maxCount;
                }
            }
            if (CollectionUtils.isNotEmpty(photos)) {
                List<WorkOrderReportPhotoReformInnerVO> r_photos = photos.stream().filter(Objects::nonNull).collect(Collectors.toList());
                for (int j = 0; j < r_photos.size(); j += data.getPer_ppt_photo_nums()) {
                    int max = j + data.getPer_ppt_photo_nums();
                    if (max > r_photos.size()) max = r_photos.size();
                    setPointPage2(ppt, ppt.getSlides().size(), data.getPer_ppt_photo_nums(), r_photos.subList(j, max));
                }
            }
        }


        String outPath = outFileSpace + File.separator + fileName;
        try {
            FileOutputStream out = new FileOutputStream(outPath);
            ppt.write(out);
            out.close();
        } catch (IOException e) {
            log.error(e);
            e.printStackTrace();
        }
        return outPath;
    }

    public String genWorkOrderReport(WorkOrderReportInfoDTO data, String modelPath, String outFileSpace, String fileName) {
        // 读取ppt模板
        XMLSlideShow ppt = null;
        try {
            FileInputStream is = new FileInputStream(modelPath);
            ppt = new XMLSlideShow(is);
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (ppt == null) return "";

        // 首页
        // 替换文本map
        HashMap<String, String> replaceMap = new HashMap<>();
        replaceMap.put("${companyName}", StringUtils.defaultString(data.getCompany_name(), ""));
        replaceMap.put("${title}", StringUtils.defaultString(data.getTitle(), ""));
        replaceMap.put("${subTitle}", StringUtils.defaultString(data.getSub_title(), ""));
        replaceMap.put("${count}", "点位：" + StringUtils.defaultString(data.getCount() != null ? data.getCount().toString() : "0") + "个");
        replaceMap.put("${customerName}", data.getShow_customer() ? ("客户：" + StringUtils.defaultString(data.getCustomer_name(), "")) : "");
        replaceMap.put("${type}", StringUtils.defaultString(data.getType(), ""));
        List<String> daterangeList = data.getDaterange();
        if (CollectionUtils.isEmpty(daterangeList)) daterangeList = new ArrayList<>();
        if (!data.getShow_daterange()) daterangeList = new ArrayList<>();
        daterangeList.add("制作日期：" + data.getCreate_time());
        String daterangeStr = String.join("\r", daterangeList);
        replaceMap.put("${daterange}", StringUtils.defaultString(daterangeStr, ""));

        int buildingExtraTurns = 0;

        Dimension pptPageSize = ppt.getPageSize();
        log.info("ppt_w:{},ppt_h:{}", pptPageSize.getWidth(), pptPageSize.getHeight());

        List<XSLFSlide> slides = ppt.getSlides();
        for (int i = 0; i < slides.size(); i++) {
            XSLFSlide slide = slides.get(i);
            List<XSLFShape> shapes = slide.getShapes();

            if (i == 0) {
                // 首页替换文本
                for (XSLFShape shape : shapes) {
                    //修改文本数据利用textshape
                    if (shape instanceof TextShape) {
                        List<XSLFTextParagraph> textParagraphs = ((TextShape) shape).getTextParagraphs();
                        if (textParagraphs == null || textParagraphs.size() == 0) {
                            continue;
                        }
                        replaceText(textParagraphs, replaceMap);
                    }
                }
            }

            if (i == 2) {
                // 第三页
                boolean hasNextTablePage = false;
                String[][] remainBs = null;
                int dataLength = 0;
                for (XSLFShape shape : shapes) {
                    if (shape instanceof XSLFTable) {
                        XSLFTable table = (XSLFTable) shape;
                        // 设置标题行
                        setBuildingHeader(table, data.getBuildingTableHeader());

                        /** 设置表格 x ,y ,width,height **/
                        Rectangle2D tableAnchor = table.getAnchor();
                        Rectangle2D toTableAnchor = new Rectangle2D.Double(((pptPageSize.getWidth() - tableAnchor.getWidth()) / 2),
                                tableAnchor.getY(), tableAnchor.getWidth(), tableAnchor.getHeight());
                        table.setAnchor(toTableAnchor);

                        // 插入表格行
                        String[][] originBs = data.getBuildingTableData();
                        if (originBs != null) {
                            int firstLength = Math.min(originBs.length, 10);
                            dataLength = data.getBuildingTableHeader().length;
                            String[][] firstBs = new String[firstLength][dataLength];
                            if (originBs.length <= 10) {
                                firstBs = originBs;
                                remainBs = null;
                            } else {
                                System.arraycopy(originBs, 0, firstBs, 0, 10);
                                hasNextTablePage = true;
                                remainBs = new String[originBs.length - 10][dataLength];
                                System.arraycopy(originBs, 10, remainBs, 0, originBs.length - 10);
                            }
                            addBuildingData(table, firstBs, 1);
                        }
                    }
                }
                if (hasNextTablePage && remainBs != null) {
                    int pageSize = 15;
                    int remainLength = remainBs.length;
                    buildingExtraTurns = remainLength / pageSize;
                    int mod = remainLength % pageSize;
                    if (mod > 0) buildingExtraTurns++;
                    for (int j = 1; j <= buildingExtraTurns; j++) {
                        int max = j * pageSize;
                        if (max > remainLength) max = remainLength;
                        int curLength = max - (j - 1) * pageSize;
                        String[][] curDatas = new String[curLength][dataLength];
                        System.arraycopy(remainBs, (j - 1) * pageSize, curDatas, 0, curLength);
                        XSLFSlide newSlide = copySlide(ppt, slides.get(3), 3 + j);
                        for (XSLFShape shape : newSlide.getShapes()) {
                            if (shape instanceof XSLFTable) {
                                XSLFTable table = (XSLFTable) shape;
                                // 设置标题行
                                setBuildingHeader(table, data.getBuildingTableHeader());

                                /** 设置表格 x ,y ,width,height **/
                                Rectangle2D tableAnchor = table.getAnchor();
                                Rectangle2D toTableAnchor = new Rectangle2D.Double(((pptPageSize.getWidth() - tableAnchor.getWidth()) / 2),
                                        tableAnchor.getY(), tableAnchor.getWidth(), tableAnchor.getHeight());
                                table.setAnchor(toTableAnchor);

                                // 插入表格行
                                addBuildingData(table, curDatas, 11 + (j - 1) * pageSize);
                            }
                        }
                    }
                }
            }
        }
        ppt.removeSlide(3);
        int[] index = new int[1];
        index[0] = 1;
        if (CollectionUtils.isNotEmpty(data.getImg_origin_list())) {
            for (int j = 0; j < data.getImg_origin_list().size(); j += data.getPer_ppt_photo_nums()) {
                int max = j + data.getPer_ppt_photo_nums();
                if (max > data.getImg_origin_list().size()) max = data.getImg_origin_list().size();
                {
                    setOriginImgArr(ppt, ppt.getSlides().size() - 2, data.getPer_ppt_photo_nums(), data.getImg_origin_list().subList(j, max), index);
                }
            }
        }
        if (CollectionUtils.isNotEmpty(data.getPhotos())) {
            for (int i = 0; i < data.getPhotos().size(); i++) {
                WorkOrderReportPhotoReformVO building = data.getPhotos().get(i);
                setBuildingPage(ppt, ppt.getSlides().size() - 1, building);
                if (building.getDaterangeVOs().size() > 0) {
                    for (WorkOrderReportPhotoReformDateRangeVO dateRangeVO : building.getDaterangeVOs()) {
                        List<WorkOrderReportPhotoReformInnerVO> points = dateRangeVO.getPoints();
                        if (CollectionUtils.isNotEmpty(points)) {
                            for (int j = 0; j < points.size(); j += data.getPer_ppt_photo_nums()) {
                                int max = j + data.getPer_ppt_photo_nums();
                                if (max > points.size()) max = points.size();
                                {
                                    setPointPage(ppt, ppt.getSlides().size() - 1, data.getPer_ppt_photo_nums(), j,
                                            building.getBuilding_area(), building.getCount().toString(), dateRangeVO.getDaterange(), points.subList(j, max));
                                }
                            }
                        }
                    }
                }
            }
        }

        String outPath = outFileSpace + File.separator + fileName;
        try {
            FileOutputStream out = new FileOutputStream(outPath);
            ppt.write(out);
            out.close();
        } catch (IOException e) {
            log.error(e);
            e.printStackTrace();
        }
        return outPath;
    }

    private void setBuildingHeader(XSLFTable table, String[] headers) {
        XSLFTableRow headerRow = table.getRows().get(0);
        List<XSLFTableCell> headerCells = table.getRows().get(0).getCells();
        if (headerCells.size() < headers.length) {
            int startIndex = headerCells.size();
            Color bgColor = new Color(48, 141, 162);
            for (int i = 0; i < headerCells.size(); i++) {
                headerCells.get(i).setText(headers[i]);
                setHeaderCell(headerRow, headers[i], bgColor, Color.WHITE, headerCells.get(i));
            }
            for (int i = startIndex; i < headers.length; i++) {
                setHeaderCell(headerRow, headers[i], bgColor, Color.WHITE);
            }
        }
        headerRow.setHeight(24);
    }

    private void addBuildingData(XSLFTable table, String[][] datas, Integer minIndex) {
        if (ArrayUtils.isNotEmpty(datas)) {
            for (int i = 0; i < datas.length; i++) {
                int index = i + minIndex;
                Color bgColor = index % 2 == 0 ? new Color(116, 196, 214) : new Color(233, 236, 244);
                String[] rowData = datas[i];
                XSLFTableRow tableRow = table.addRow(); //创建表格行
                for (String data : rowData) {
                    addCell(tableRow, data, bgColor);
                }
                tableRow.setHeight(24);
            }
        }
    }

    private void setHeaderCell(XSLFTableRow tableRow, String text, Color bgColor, Color fontColor, XSLFTableCell... cell) {
        XSLFTableCell tableCell = null;
        if (cell != null && cell.length == 1) {
            tableCell = cell[0];
            tableCell.clearText();
        } else tableCell = tableRow.addCell();//创建表格单元格
        XSLFTextParagraph p = tableCell.addNewTextParagraph();
        XSLFTextRun tr = p.addNewTextRun();
        tr.setText(text);
        tr.setFontSize(12d);
        tr.setFontColor(fontColor);
        tableCell.setFillColor(bgColor);
        p.setTextAlign(TextParagraph.TextAlign.CENTER);
        tableCell.setVerticalAlignment(VerticalAlignment.MIDDLE);
        tableCell.resizeToFitText();

        tableCell.removeBorder(TableCell.BorderEdge.top);
        tableCell.removeBorder(TableCell.BorderEdge.bottom);
        tableCell.removeBorder(TableCell.BorderEdge.left);
        tableCell.removeBorder(TableCell.BorderEdge.right);

        /** 设置单元格的边框颜色 **/
        tableCell.setBorderColor(TableCell.BorderEdge.top, Color.WHITE);
        tableCell.setBorderColor(TableCell.BorderEdge.bottom, Color.WHITE);
        tableCell.setBorderColor(TableCell.BorderEdge.left, Color.WHITE);
        tableCell.setBorderColor(TableCell.BorderEdge.right, Color.WHITE);

        /** 设置单元格边框 **/
        tableCell.setBorderWidth(TableCell.BorderEdge.top, 1);
        tableCell.setBorderWidth(TableCell.BorderEdge.bottom, 1);
        tableCell.setBorderWidth(TableCell.BorderEdge.left, 1);
        tableCell.setBorderWidth(TableCell.BorderEdge.right, 1);
    }

    private void addCell(XSLFTableRow tableRow, String text, Color bgColor, Color... fontColor) {
        XSLFTableCell tableCell = tableRow.addCell();//创建表格单元格
        XSLFTextParagraph p = tableCell.addNewTextParagraph();
        XSLFTextRun tr = p.addNewTextRun();
        tr.setText(text);
        tr.setFontSize(12d);
        tr.setFontColor(fontColor != null && fontColor.length == 1 ? fontColor[0] : Color.BLACK);
        tableCell.setFillColor(bgColor);
        p.setTextAlign(TextParagraph.TextAlign.CENTER);
        tableCell.setVerticalAlignment(VerticalAlignment.MIDDLE);
    }

    private void setPointPage2(XMLSlideShow ppt, Integer toIndex, Integer per_ppt_photo_nums,
                               List<WorkOrderReportPhotoReformInnerVO> points) {
        XSLFSlide slide = ppt.createSlide();

        double p_m_w = 920; // 图片总宽度
        double p_m_h = 0; // 图片高度
        double p_m_h_w = 0; // 根据高度计算最大宽度
        double per_point_w = 0; // 根据一页几张计算宽度
        double actual_w = 0;
        double actual_h = 0;
        double per_out_lr = 0;
        double per_out_tb = 0;
        int rowNum = 1;

        // 每页图片数量为2时
        double actual_w_2 = 0;
        double per_out_lr_2 = 0;

        if (per_ppt_photo_nums == 2 || per_ppt_photo_nums == 3 || per_ppt_photo_nums == 4) {
            // 单行
            p_m_h = 390;
            p_m_h_w = p_m_h / 4 * 3;
            per_point_w = p_m_w / per_ppt_photo_nums;
            actual_w = Math.min(p_m_h_w, per_point_w);
            actual_h = actual_w / 3 * 4;
            per_out_lr = (960 - actual_w * per_ppt_photo_nums) / (per_ppt_photo_nums + 1);
            per_out_tb = (500 - actual_h) / 2;
        }

        if (per_ppt_photo_nums == 8) {
            // 双行
            p_m_h = 370;
            p_m_h_w = p_m_h / 8 * 3;
            per_point_w = p_m_w / 4;
            actual_w = Math.min(p_m_h_w, per_point_w);
            actual_h = actual_w / 3 * 4;
            per_out_lr = (960 - actual_w * 4) / (4 + 1);
            per_out_tb = (480 - actual_h * 2) / 3;
            rowNum = 2;
        }

        if (per_ppt_photo_nums == 2) {
            per_out_lr_2 = 15;
            actual_w_2 = new BigDecimal((960 - per_out_lr_2 * 3) / 2).setScale(2, 2).doubleValue();
        }


        for (int i = 0; i < points.size(); i++) {
            WorkOrderReportPhotoReformInnerVO point = points.get(i);

            //double x = (i / 4 > 0 ? (i - 4) : i) * (actual_w + per_out_lr) + per_out_lr;
            double x = (i / 4 > 0 ? (i - 4) : i) * (per_ppt_photo_nums == 2 ? actual_w_2 + per_out_lr_2 : actual_w + per_out_lr) + (per_ppt_photo_nums == 2 ? per_out_lr_2 : per_out_lr);
            byte[] bt = openFile(point.getUrl());
            XSLFPictureShape pictureShape = null;
            HashMap<String, Double> whs = new HashMap<>();
            if (bt != null && bt.length > 0) {
                XSLFPictureData xslfPictureData = ppt.addPicture(bt, XSLFPictureData.PictureType.PNG);
                pictureShape = slide.createPicture(xslfPictureData);
                //whs = getPicWH(xslfPictureData, actual_w, actual_h);
                // 设置横版图片尺寸
                Dimension de = xslfPictureData.getImageDimension();
                double w = de.getWidth();
                double h = de.getHeight();
                if (per_ppt_photo_nums == 2) {
                    if (w > h) {
                        double s_w = new BigDecimal(w * actual_h / h).setScale(2, 2).doubleValue(); // 宽高比计算后的宽度
                        double f_w = actual_w_2;
                        double f_h = actual_h;
                        if (s_w > actual_w_2)
                            f_h = new BigDecimal(actual_w_2 * actual_h / s_w).setScale(2, 2).doubleValue();
                        whs.put("w", f_w);
                        whs.put("h", f_h);
                        whs.put("actual_w", f_w);
                    } else {
                        whs = getPicWH(de, actual_w, actual_h);
                        x = (i % 2 == 0 ? 0 : actual_w_2) + (actual_w_2 - actual_w) / 2 + per_out_lr_2;
                    }
                } else whs = getPicWH(de, actual_w, actual_h);
            }
            double w = whs.get("w") != null ? whs.get("w") : 250;
            double h = whs.get("h") != null ? whs.get("h") : 0;
            //double ac_x = x + (actual_w - w) / 2;
            double ac_x = x + ((whs.get("actual_w") != null ? whs.get("actual_w") : w) - w) / 2;
            double ac_y = (i / 4 > 0 ? (20 + 2 * per_out_tb + actual_h) : per_out_tb) + (actual_h - h) / 2;
            if (pictureShape != null) pictureShape.setAnchor(new Rectangle2D.Double(ac_x, ac_y, w, h));


            XSLFTextBox pointNameBox = slide.createTextBox();
            pointNameBox.setAnchor(new Rectangle2D.Double(ac_x, ac_y + h + 10, w, rowNum == 1 ? 14 : 10));
            pointNameBox.setVerticalAlignment(VerticalAlignment.MIDDLE);
            XSLFTextParagraph pointNameP = pointNameBox.addNewTextParagraph();
            pointNameP.setTextAlign(TextParagraph.TextAlign.CENTER);
            XSLFTextRun pointName_prev = pointNameP.addNewTextRun();
            pointNameP.addLineBreak();
            XSLFTextRun pointName = pointNameP.addNewTextRun();
            pointName_prev.setFontFamily("Microsoft YaHei");
            pointName_prev.setFontColor(Color.BLACK);
            pointName_prev.setFontSize(rowNum == 1 ? 14d : 10d);
            String point_name_str_prev = point.getIdx() + "、【" + point.getBuilding_area() + "】";
            pointName_prev.setText(point_name_str_prev);
            pointName.setFontFamily("Microsoft YaHei");
            pointName.setFontColor(Color.BLACK);
            pointName.setFontSize(rowNum == 1 ? 14d : 10d);
            String point_name_str = "";
            if (point.getPoint_type_id() == 1) {
                point_name_str = point_name_str + (StringUtils.isNotEmpty(point.getBuilding_number()) ? point.getBuilding_number() + "号楼" : "")
                        + (StringUtils.isNotEmpty(point.getUnit_number()) ? point.getUnit_number() + "单元" : "")
                        + (StringUtils.isNotEmpty(point.getFloor()) ? point.getFloor() + "层" : "");
            } else if (point.getPoint_type_id() == 2) {
                point_name_str = point_name_str + (StringUtils.isNotEmpty(point.getDoor_number()) ? point.getDoor_number() + "号门" : "")
                        + (StringUtils.isNotEmpty(point.getRail_number()) ? point.getRail_number() + "号护栏" : "");
            }
            //对文字进行修改 改成显示设备Code
            point_name_str = point_name_str + ((StringUtils.isNotEmpty(point.getCode())) ? "(" + point.getCode() + ")" : "");
//                    + (StringUtils.isNotEmpty(point.getMedia_feature())?"（"+point.getMedia_feature()+"）":"")
//                    + (StringUtils.isNotEmpty(point.getSize())?"（"+point.getSize()+"）":"");

            pointName.setText(point_name_str);
        }


        ppt.setSlideOrder(slide, toIndex);
    }

    private void setPointPage(XMLSlideShow ppt, Integer toIndex, Integer per_ppt_photo_nums, Integer startIndex,
                              String building_area_str, String count_str, String daterange_str,
                              List<WorkOrderReportPhotoReformInnerVO> points) {
        XSLFSlide slide = ppt.createSlide();

        XSLFAutoShape rightShape = slide.createAutoShape();
        rightShape.setAnchor(new Rectangle2D.Double(0, 432, 960, 108));
        rightShape.setFillColor(new Color(211, 67, 40));

        XSLFTextBox nameBox = slide.createTextBox();
        nameBox.setAnchor(new Rectangle2D.Double(30, 440, 900, 36));
        nameBox.setVerticalAlignment(VerticalAlignment.MIDDLE);
        XSLFTextParagraph nameP = nameBox.addNewTextParagraph();
        nameP.setTextAlign(TextParagraph.TextAlign.CENTER);
        XSLFTextRun name = nameP.addNewTextRun();
        name.setFontFamily("Microsoft YaHei");
        name.setFontColor(Color.WHITE);
        name.setText(building_area_str);
        name.setFontSize(36d);

        XSLFTextBox countBox = slide.createTextBox();
        countBox.setAnchor(new Rectangle2D.Double(30, 480, 900, 16));
        countBox.setVerticalAlignment(VerticalAlignment.MIDDLE);
        XSLFTextParagraph countP = countBox.addNewTextParagraph();
        countP.setTextAlign(TextParagraph.TextAlign.CENTER);
        XSLFTextRun count = countP.addNewTextRun();
        count.setFontFamily("Microsoft YaHei");
        count.setFontColor(Color.WHITE);
        count.setText("数量：" + count_str);
        count.setFontSize(16d);

        XSLFTextBox dateBox = slide.createTextBox();
        dateBox.setAnchor(new Rectangle2D.Double(30, 500, 900, 15));
        dateBox.setVerticalAlignment(VerticalAlignment.MIDDLE);
        XSLFTextParagraph dateP = dateBox.addNewTextParagraph();
        dateP.setTextAlign(TextParagraph.TextAlign.CENTER);
        XSLFTextRun date = dateP.addNewTextRun();
        date.setFontFamily("Microsoft YaHei");
        date.setFontColor(Color.WHITE);
        date.setText(daterange_str);
        date.setFontSize(15d);

        double p_m_w = 920; // 图片总宽度
        double p_m_h = 0; // 图片高度
        double p_m_h_w = 0; // 根据高度计算最大宽度
        double per_point_w = 0; // 根据一页几张计算宽度
        double actual_w = 0;
        double actual_h = 0;
        double per_out_lr = 0;
        double per_out_tb = 0;
        int rowNum = 1;

        // 每页图片数量为2时
        double actual_w_2 = 0;
        double per_out_lr_2 = 0;

        if (per_ppt_photo_nums == 2 || per_ppt_photo_nums == 3 || per_ppt_photo_nums == 4) {
            // 单行
            p_m_h = 390;
            p_m_h_w = p_m_h / 4 * 3;
            per_point_w = p_m_w / per_ppt_photo_nums;
            actual_w = Math.min(p_m_h_w, per_point_w);
            actual_h = actual_w / 3 * 4;
            per_out_lr = (960 - actual_w * per_ppt_photo_nums) / (per_ppt_photo_nums + 1);
            per_out_tb = (412 - actual_h) / 2;
        }

        if (per_ppt_photo_nums == 8) {
            // 双行
            p_m_h = 370;
            p_m_h_w = p_m_h / 8 * 3;
            per_point_w = p_m_w / 4;
            actual_w = Math.min(p_m_h_w, per_point_w);
            actual_h = actual_w / 3 * 4;
            per_out_lr = (960 - actual_w * 4) / (4 + 1);
            per_out_tb = (392 - actual_h * 2) / 3;
            rowNum = 2;
        }

        if (per_ppt_photo_nums == 2) {
            per_out_lr_2 = 15;
            actual_w_2 = new BigDecimal((960 - per_out_lr_2 * 3) / 2).setScale(2, 2).doubleValue();
        }

        for (int i = 0; i < points.size(); i++) {
            WorkOrderReportPhotoReformInnerVO point = points.get(i);

            double x = (i / 4 > 0 ? (i - 4) : i) * (per_ppt_photo_nums == 2 ? actual_w_2 + per_out_lr_2 : actual_w + per_out_lr) + (per_ppt_photo_nums == 2 ? per_out_lr_2 : per_out_lr);
            byte[] bt = openFile(point.getUrl());
            XSLFPictureShape pictureShape = null;
            HashMap<String, Double> whs = new HashMap<>();
            if (bt != null && bt.length > 0) {
                XSLFPictureData xslfPictureData = ppt.addPicture(bt, XSLFPictureData.PictureType.PNG);
                pictureShape = slide.createPicture(xslfPictureData);
                // 设置横版图片尺寸
                Dimension de = xslfPictureData.getImageDimension();
                double w = de.getWidth();
                double h = de.getHeight();
                if (per_ppt_photo_nums == 2) {
                    if (w > h) {
                        double s_w = new BigDecimal(w * actual_h / h).setScale(2, 2).doubleValue(); // 宽高比计算后的宽度
                        double f_w = actual_w_2;
                        double f_h = actual_h;
                        if (s_w > actual_w_2)
                            f_h = new BigDecimal(actual_w_2 * actual_h / s_w).setScale(2, 2).doubleValue();
                        whs.put("w", f_w);
                        whs.put("h", f_h);
                        whs.put("actual_w", f_w);
                    } else {
                        whs = getPicWH(de, actual_w, actual_h);
                        x = (i % 2 == 0 ? 0 : actual_w_2) + (actual_w_2 - actual_w) / 2 + per_out_lr_2;
                    }
                } else whs = getPicWH(de, actual_w, actual_h);
            }
            double w = whs.get("w") != null ? whs.get("w") : 250;
            double h = whs.get("h") != null ? whs.get("h") : 0;
            double ac_x = x + ((whs.get("actual_w") != null ? whs.get("actual_w") : w) - w) / 2;
            double ac_y = (i / 4 > 0 ? (20 + 2 * per_out_tb + actual_h) : per_out_tb) + (actual_h - h) / 2;
            if (pictureShape != null) pictureShape.setAnchor(new Rectangle2D.Double(ac_x, ac_y, w, h));


            XSLFTextBox pointNameBox = slide.createTextBox();
            pointNameBox.setAnchor(new Rectangle2D.Double(ac_x, ac_y + h + 2, w, rowNum == 1 ? 16 : 12));
            pointNameBox.setVerticalAlignment(VerticalAlignment.MIDDLE);
            XSLFTextParagraph pointNameP = pointNameBox.addNewTextParagraph();
            pointNameP.setTextAlign(TextParagraph.TextAlign.CENTER);
            XSLFTextRun pointName = pointNameP.addNewTextRun();
            pointName.setFontFamily("Microsoft YaHei");
            pointName.setFontColor(Color.BLACK);
            pointName.setFontSize(rowNum == 1 ? 16d : 12d);
            /*String point_name_str = String.valueOf(startIndex + i + 1)+"、";*/
            String point_name_str = point.getIdx() + "、";
            if (point.getPoint_type_id() == 1) {
                point_name_str = point_name_str + (StringUtils.isNotEmpty(point.getBuilding_number()) ? point.getBuilding_number() + "号楼" : "")
                        + (StringUtils.isNotEmpty(point.getUnit_number()) ? point.getUnit_number() + "单元" : "")
                        + (StringUtils.isNotEmpty(point.getFloor()) ? point.getFloor() + "层" : "");
            } else if (point.getPoint_type_id() == 2) {
                point_name_str = point_name_str + (StringUtils.isNotEmpty(point.getDoor_number()) ? point.getDoor_number() + "号门" : "")
                        + (StringUtils.isNotEmpty(point.getRail_number()) ? point.getRail_number() + "号护栏" : "");
            }
            //对文字进行修改 改成显示设备Code
            point_name_str = point_name_str + ((StringUtils.isNotEmpty(point.getCode())) ? "(" + point.getCode() + ")" : "");
//                    + (StringUtils.isNotEmpty(point.getMedia_feature())?"（"+point.getMedia_feature()+"）":"")
//                    + (StringUtils.isNotEmpty(point.getSize())?"（"+point.getSize()+"）":"");

            pointName.setText(point_name_str);
        }


        ppt.setSlideOrder(slide, toIndex);
    }

    private void setBuildingPage(XMLSlideShow ppt, Integer toIndex, WorkOrderReportPhotoReformVO building) {
        XSLFSlide slide = ppt.createSlide();

        boolean hasBuildingPhoto = StringUtils.isNotEmpty(building.getBuilding_area_photo());

        XSLFAutoShape rightShape = slide.createAutoShape();
        rightShape.setAnchor(new Rectangle2D.Double(hasBuildingPhoto ? 480 : 0, 0, hasBuildingPhoto ? 480 : 960, 540));
        rightShape.setFillColor(new Color(211, 67, 40));

        XSLFTextBox nameBox = slide.createTextBox();
        nameBox.setAnchor(new Rectangle2D.Double(hasBuildingPhoto ? 520 : 40, 75, hasBuildingPhoto ? 400 : 880, 40));
        nameBox.setVerticalAlignment(VerticalAlignment.MIDDLE);
        XSLFTextParagraph nameP = nameBox.addNewTextParagraph();
        nameP.setTextAlign(TextParagraph.TextAlign.CENTER);
        XSLFTextRun name = nameP.addNewTextRun();
        name.setFontFamily("Microsoft YaHei");
        name.setFontColor(Color.WHITE);
        name.setText(building.getBuilding_area());
        name.setFontSize(40d);

        XSLFTextBox countBox = slide.createTextBox();
        countBox.setAnchor(new Rectangle2D.Double(hasBuildingPhoto ? 520 : 40, 400, hasBuildingPhoto ? 400 : 880, 16));
        countBox.setVerticalAlignment(VerticalAlignment.MIDDLE);
        XSLFTextParagraph countP = countBox.addNewTextParagraph();
        countP.setTextAlign(TextParagraph.TextAlign.CENTER);
        XSLFTextRun count = countP.addNewTextRun();
        count.setFontFamily("Microsoft YaHei");
        count.setFontColor(Color.WHITE);
        count.setText("数量：" + building.getCount());
        count.setFontSize(16d);

        if (CollectionUtils.isNotEmpty(building.getDateranges())) {
            List<String> dateranges = new ArrayList<>(building.getDateranges());
            for (int i = 0; i < dateranges.size(); i++) {
                String daterange = dateranges.get(i);
                XSLFTextBox dateBox = slide.createTextBox();
                dateBox.setAnchor(new Rectangle2D.Double(hasBuildingPhoto ? 520 : 40, 418 + (i * 15), hasBuildingPhoto ? 400 : 880, 15));
                dateBox.setVerticalAlignment(VerticalAlignment.MIDDLE);
                XSLFTextParagraph dateP = dateBox.addNewTextParagraph();
                dateP.setTextAlign(TextParagraph.TextAlign.CENTER);
                XSLFTextRun date = dateP.addNewTextRun();
                date.setFontFamily("Microsoft YaHei");
                date.setFontColor(Color.WHITE);
                date.setText(daterange);
                date.setFontSize(15d);
            }
        }

        if (StringUtils.isNotEmpty(building.getBuilding_area_photo())) {
            byte[] bt1 = openFile(building.getBuilding_area_photo());
            if (bt1 != null && bt1.length > 0) {
                XSLFPictureData xslfPictureData = ppt.addPicture(bt1, XSLFPictureData.PictureType.PNG);
                XSLFPictureShape pictureShape = slide.createPicture(xslfPictureData);
                HashMap<String, Double> whs = getPicWH(xslfPictureData, 320, 360);
                double w = whs.get("w");
                double h = whs.get("h");
                pictureShape.setAnchor(new Rectangle2D.Double((480 - w) / 2, (540 - h) / 2, w, h));
            }
        }
        ppt.setSlideOrder(slide, toIndex);
    }

    private void setOriginImgArr(XMLSlideShow ppt, Integer toIndex, Integer per_ppt_photo_nums, List<String> originList, int[] index) {
        XSLFSlide slide = ppt.createSlide();
        double p_m_w = 920; // 图片总宽度
        double p_m_h = 0; // 图片高度
        double p_m_h_w = 0; // 根据高度计算最大宽度
        double per_point_w = 0; // 根据一页几张计算宽度
        double actual_w = 0;
        double actual_h = 0;
        double per_out_lr = 0;
        double per_out_tb = 0;
        int rowNum = 1;

        if (per_ppt_photo_nums == 2 || per_ppt_photo_nums == 3 || per_ppt_photo_nums == 4) {
            // 单行
            p_m_h = 390;
            p_m_h_w = p_m_h / 4 * 3;
            per_point_w = p_m_w / per_ppt_photo_nums;
            actual_w = Math.min(p_m_h_w, per_point_w);
            actual_h = actual_w / 3 * 4;
            per_out_lr = (960 - actual_w * per_ppt_photo_nums) / (per_ppt_photo_nums + 1);
            per_out_tb = (412 - actual_h) / 2;
        }

        if (per_ppt_photo_nums == 8) {
            // 双行
            p_m_h = 370;
            p_m_h_w = p_m_h / 8 * 3;
            per_point_w = p_m_w / 4;
            actual_w = Math.min(p_m_h_w, per_point_w);
            actual_h = actual_w / 3 * 4;
            per_out_lr = (960 - actual_w * 4) / (4 + 1);
            per_out_tb = (392 - actual_h * 2) / 3;
            rowNum = 2;
        }


        for (int i = 0; i < originList.size(); i++) {
            WorkOrderReportPhotoReformInnerVO point = new WorkOrderReportPhotoReformInnerVO();
            point.setUrl(originList.get(i));
            if (StringUtils.isEmpty(point.getUrl()))
                continue;
            double x = (i / 4 > 0 ? (i - 4) : i) * (actual_w + per_out_lr) + per_out_lr;
            byte[] bt = openFile(point.getUrl());
            XSLFPictureShape pictureShape = null;
            HashMap<String, Double> whs = new HashMap<>();
            if (bt != null && bt.length > 0) {
                XSLFPictureData xslfPictureData = ppt.addPicture(bt, XSLFPictureData.PictureType.PNG);
                pictureShape = slide.createPicture(xslfPictureData);
                whs = getPicWH(xslfPictureData, actual_w, actual_h);
            }
            double w = whs.get("w") != null ? whs.get("w") : 250;
            double h = whs.get("h") != null ? whs.get("h") : 0;
            double ac_x = x + (actual_w - w) / 2;
            double ac_y = (i / 4 > 0 ? (20 + 2 * per_out_tb + actual_h) : per_out_tb) + (actual_h - h) / 2;
            if (pictureShape != null) pictureShape.setAnchor(new Rectangle2D.Double(ac_x, ac_y, w, h));
            XSLFTextBox pointNameBox = slide.createTextBox();
            pointNameBox.setAnchor(new Rectangle2D.Double(ac_x, ac_y + h + 2, w, rowNum == 1 ? 16 : 12));
            pointNameBox.setVerticalAlignment(VerticalAlignment.MIDDLE);
            XSLFTextParagraph pointNameP = pointNameBox.addNewTextParagraph();
            pointNameP.setTextAlign(TextParagraph.TextAlign.CENTER);
            XSLFTextRun pointName = pointNameP.addNewTextRun();
            pointName.setFontFamily("Microsoft YaHei");
            pointName.setFontColor(Color.BLACK);
            pointName.setFontSize(rowNum == 1 ? 16d : 12d);
            String point_name_str = "";
            if (originList.size() > 1 || index[0] != 1) {
                point_name_str += "原图" + (index[0]);
            } else {
                point_name_str += "原图";
            }
            pointName.setText(point_name_str);
            index[0]++;
        }
        ppt.setSlideOrder(slide, toIndex);
    }

    private HashMap<String, Double> getPicWH(XSLFPictureData data, double m_w, double m_h) {
        return getPicWH(data.getImageDimension(), m_w, m_h);
    }

    private HashMap<String, Double> getPicWH(Dimension de, double m_w, double m_h) {
        HashMap<String, Double> returnMap = new HashMap<>();
        double w = de.getWidth();
        double h = de.getHeight();
        returnMap.put("w", w);
        returnMap.put("h", h);
        returnMap.put("actual_w", m_w);
        double r_w = w;
        double r_h = h;
        if (w > m_w || h > m_h) {
            double scale_w = m_w / w;
            double scale_h = m_h / h;
            if (w > m_w && h > m_h) {
                if (scale_w <= scale_h) {
                    r_w = scale_w * w;
                    r_h = scale_w * h;
                } else {
                    r_w = scale_h * w;
                    r_h = scale_h * h;
                }
            } else if (w > m_w) {
                r_w = scale_w * w;
                r_h = scale_w * h;
            } else if (h > m_h) {
                r_w = scale_h * w;
                r_h = scale_h * h;
            }

            returnMap.put("w", r_w);
            returnMap.put("h", r_h);
            returnMap.put("actual_w", r_w);
        }
        return returnMap;
    }

    private XSLFSlide copySlide(XMLSlideShow ppt, XSLFSlide slide, Integer toIndex) {
        XSLFSlide s1 = ppt.createSlide();
        List<XSLFShape> shapes = slide.getShapes();
        if (shapes.size() > 0) {
            for (XSLFShape shape : shapes) {
                s1.importContent(shape.getSheet());
                Rectangle2D anchor = shape.getAnchor();
                log.info("{},{},{},{}", anchor.getX(), anchor.getY(), anchor.getWidth(), anchor.getHeight());
            }
        }
        ppt.setSlideOrder(s1, toIndex);
        return s1;
    }

    /**
     * 替换文本
     */
    private void replaceText(List<XSLFTextParagraph> list, Map<String, String> textMap) {
        if (list == null || list.size() <= 0) {
            return;
        }
        Pattern pattern = Pattern.compile("\\$\\{\\w+\\}");
        Pattern pattern2 = Pattern.compile("\\w*\\}");
        Pattern pattern3 = Pattern.compile("\\$\\{\\w*");

        for (XSLFTextParagraph textParagraph : list) {
            if (textParagraph == null) {
                continue;
            }
            List<XSLFTextRun> textRuns = textParagraph.getTextRuns();
            if (textRuns == null || textRuns.size() <= 0) {
                continue;
            }
            StringBuilder target = new StringBuilder();
            XSLFTextRun targetRun = null;
            for (XSLFTextRun textRun : textRuns) {
                if (textRun == null) {
                    continue;
                }
                String text = textRun.getRawText();
                if (StringUtils.isBlank(text)) {
                    continue;
                }
                //检测开始标记
                if (text.contains("${") && text.contains("}")) {
                    Matcher matcher = pattern.matcher(text.trim());
                    if (matcher.find()) {
                        String originStr = matcher.group(0);
                        String finalText = matcher.group(0);
                        finalText = textMap.getOrDefault(finalText, "");
                        textRun.setText(text.replace(originStr, finalText));
                    }
                } else if (text.contains("${") && !text.contains("}")) {
                    Matcher matcher = pattern3.matcher(text.trim());
                    if (matcher.find()) {
                        target.append(matcher.group(0));
                        targetRun = textRun;
                    }
                } else if (null != targetRun && text.contains("}")) {
                    Matcher matcher = pattern2.matcher(text.trim());
                    if (matcher.find()) {
                        String finalText = target.append(matcher.group(0)).toString();
                        finalText = textMap.getOrDefault(finalText, "");
                        target.delete(0, target.length());
                        targetRun.setText(finalText);
                        targetRun = null;
                        textRun.setText("");
                    }
                } else if (null != targetRun && !text.contains("}")) {
                    target.append(textRun.getRawText().trim());
                    textRun.setText("");
                }
            }
        }

    }

    private byte[] openFile(String filePath) {
//        如果是生产环境
        if (useOss == 1 && evn.equals("prod")) {
            log.info("进入生产环境开始获取图片1:" + filePath);
            if (filePath == null || filePath.equals("") || filePath.split("/").length < 1) return null;
            String filename = filePath.split("/")[filePath.split("/").length - 1];
            log.info("进入生产环境开始获取图片2:" + filename);
            return ossAliyunUtil.innerDownloadByte(filename);
        }

        int maxTryTime = 5; //重试次数
        int curTryTime = 1; //当前次数
        byte[] bytes = null;
        while (bytes == null && curTryTime <= maxTryTime){
            try{
                if(curTryTime > 1) Thread.sleep(3000); // 非第一次请求，睡眠3秒
            }catch (Exception ignore){}

            log.info("开始获取图片:" + filePath);

            try {
                bytes = queryFileBytes(filePath);
            }catch (Exception e) {
                log.error("第"+curTryTime+"次下载图片失败："+filePath, e);
            }

            curTryTime++;
        }
        return bytes;
    }

    private byte[] queryFileBytes(String filePath) throws IOException {
        int HttpResult; // 服务器返回的状态
        byte[] bytes = null;
        URL url = new URL(filePath); // 创建URL
        URLConnection urlconn = url.openConnection(); // 试图连接并取得返回状态码
        urlconn.connect();
        HttpURLConnection httpconn = (HttpURLConnection) urlconn;
        HttpResult = httpconn.getResponseCode();
        if (HttpResult != HttpURLConnection.HTTP_OK) {
            log.error("无法连接到服务器");
            //throw new RuntimeException("无法连接到服务器");
        } else {
            int filesize = urlconn.getContentLength(); // 取数据长度
            System.out.println("取数据长度====" + filesize);
            urlconn.getInputStream();
            InputStream inputStream = urlconn.getInputStream();

            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            int ch;
            while ((ch = inputStream.read()) != -1) {
                swapStream.write(ch);
            }
            bytes = swapStream.toByteArray();
        }
        if(bytes != null) log.info("文件大小====" + bytes.length);
        return bytes;
    }
}
